Skip to content

Redact secret_request values from transcripts, pushes and memory (#1531) - #1555

Merged
currentbits merged 1 commit into
mainfrom
coder/secret-redaction
Oct 9, 2026
Merged

currentbits merged 1 commit into
mainfrom
coder/secret-redaction

Conversation

@currentbits

Copy link
Copy Markdown
Owner

Follow-up to #1542. A secret given through secret_request is in the run env, so echo $STRIPE_API_KEY used to put the value into tool output, the transcript and coder-store.json.

  • threadSecrets.redact(threadId, value) deep-replaces the thread's secret values (>= 6 chars, longest first) with [secret:NAME]. It returns the input untouched when the thread has no secrets.
  • Choke point: store.appendMessage and store.updateMessage. Every runner and adapter message write goes through one of these two. The thread:updated stream-tail push, the summaries and the terminal session record all read back from the store.
  • Paths that skip the store: the session transcript queue (user/event text on append), and the run auto-record POSTed to the memory server (/api/store). The new test caught the auto-record leaking the raw value.

Test: in electron/test/secret-request.test.js, an agent echoes $STRIPE_API_KEY, a tool result carrying the value is appended and patched, and a fake memory server captures /api/session and /api/store. The test asserts [secret:STRIPE_API_KEY] is present and the value is absent in messages, pushed details, the transcript and every file under userData. It fails when the store redaction is removed.

npm run test:electron: 4467 pass, 0 fail.

🤖 Generated with Claude Code

A secret given through secret_request rides the run env, so an agent that
runs `echo $STRIPE_API_KEY` used to put the value into tool output, the
transcript and coder-store.json.

store.appendMessage/updateMessage now replace the thread's secret values
(>= 6 chars) with [secret:NAME]. Every message write goes through those two,
and the renderer push, summaries and terminal session record read back from
the store. Two paths carry text past the store and are redacted too: the
session transcript queue (user/event on append) and the run auto-record
POSTed to the memory server, which the new test caught leaking.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T15:26:24.554748Z 24d7261 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 24d72615dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread electron/store.js
Comment on lines +2077 to +2080
// Every runner/adapter message write lands here or in updateMessage, and
// the renderer push, summaries and session transcript read back from the
// store, so redacting here covers them all (#1531 secret_request).
list.push(threadSecrets.redact(threadId, message));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Redact failure metadata before persisting it

When a provider prints a requested secret to stderr and exits nonzero, markRunFailed stores the unredacted shortError(text) in thread.lastError; this append-time redaction only protects the duplicate event message. The thread row is then written to coder-store.json and returned by listThreads, so the secret still leaks through both disk and threads:changed pushes. Apply the thread's redaction to failure/thread metadata before calling updateThread as well.

Useful? React with 👍 / 👎.

Comment thread electron/memory-record.js
await proxy.store(payload);
// The body quotes the run's final text, which may echo a secret (#1531).
await proxy.store(threadSecrets.redact(String(thread.id || ""), payload));
} catch {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redact run text before truncating it

If a secret crosses the 1,200-character boundary in the final run text, buildRunBody truncates it first, leaving only a prefix that the later exact-value replacement cannot recognize; that raw secret prefix is then posted to shared memory. This is especially significant for long credentials such as PEM values. Redact outcome.text before buildRunBody slices it rather than redacting only the completed payload.

Useful? React with 👍 / 👎.

@currentbits
currentbits merged commit 10a0714 into main Oct 9, 2026
11 of 12 checks passed
currentbits pushed a commit that referenced this pull request Oct 11, 2026
#1555 redacts secret_request values in appendMessage/updateMessage, but
work-log items (tool commands and output) were stored and pushed as is.
appendWorkLog and updateWorkLogItem now redact the incoming item/patch the
same way, so a printed $NAME leaves only [secret:NAME] behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
currentbits added a commit that referenced this pull request Oct 11, 2026
#1555 redacts secret_request values in appendMessage/updateMessage, but
work-log items (tool commands and output) were stored and pushed as is.
appendWorkLog and updateWorkLogItem now redact the incoming item/patch the
same way, so a printed $NAME leaves only [secret:NAME] behind.

Co-authored-by: Willem <willem@willems-mbp.home>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
currentbits pushed a commit that referenced this pull request Oct 19, 2026
#1555 redacts secret_request values in appendMessage/updateMessage, but
work-log items (tool commands and output) were stored and pushed as is.
appendWorkLog and updateWorkLogItem now redact the incoming item/patch the
same way, so a printed $NAME leaves only [secret:NAME] behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant